<!-- 用户管理 -->
<template>
  <el-card shadow="never" class="chat-body" ref="chatContainer">
    <template v-for="(item, index) in data" :key="index">
      <div class="message-top">
        <img src="../../../assets/images/m01.png" alt="" />
        <div class="message-text" @click="onClickTitle(item.title)">
          <span>{{ item.title }}</span>
        </div>
      </div>
      <div class="message-card">
        <div class="message-top-title">
          <img src="../../../assets/images/m02.png" alt="" />
          <!-- <div class="message-text" v-dompurify-html="item.content"></div> -->
          <MdPreview v-if="item.content" class="message-text markdown-viewer" editorId="markdown-viewer"
            :modelValue="item.content" />
          <div v-else class="message-loading">
            <span v-loading="true"></span>
          </div>
        </div>
      </div>
    </template>
    <div class="message-stop">
      <img src="../../../assets/images/m03.png" alt="" />
      <div class="message-text" @click="onClickStop">
        <span v-if="controller.stop">继续输出</span>
        <span v-else>停止输出</span>
      </div>
    </div>
  </el-card>
</template>

<script setup lang="ts">
import { ref } from "vue";
import { ChatQuery } from "@/api/ai/chat/types";
import { chat, chatKnowledge, chatApi } from "@/api/ai/chat/index";
import { QuestionHisForm } from "@/api/ai/question-his/types";
import { saveQuestionHis } from "@/api/ai/question-his/index";
import { getQuestionHisForm } from "@/api/ai/question-his/index";
import { MdPreview } from "md-editor-v3";
import "md-editor-v3/lib/preview.css";

defineOptions({
  name: "Message",
  inheritAttrs: false,
});

// 问题
const props = defineProps({
  obj: {
    type: Object,
    default: () => { },
  },
  // 历史的查询参数
  params: {
    type: Object,
    default: () => { },
  },
  knowledgeId: {
    type: String,
    default: "",
  },
});

const emits = defineEmits(["done", "reChat"]);

// 是否加载中
const loading = ref(false);

// 页面所有数据
const data = ref([]);

// 滚动条内容
const chatContainer = ref<any>(null);

const currItem: any = ref({});

const controller = {
  // 是否停止
  stop: false,
  isDone: false,
};

// 请求参数
const queryParams = reactive<ChatQuery>({
  question: props.obj.messageTitle,
  streaming: true,
});

// 监听点击文字变化
watch(
  () => props.obj,
  (newValue) => {
    if (newValue.messageTitle.slice(newValue.messageTitle.length - 1) === "&") {
      let newTitle = newValue.messageTitle.slice(0, -1);
      getQuestionHisForm(newValue.messageId).then((res) => {
        addItem(newTitle, res.data.content);
      });
    } else {
      queryParams.question = newValue.messageTitle;
      getChat();
    }
  },
  {
    deep: true,
  }
);

function onClickStop() {
  if (!controller.stop) {
    controller.stop = true;
  }
}

// 加入到数组(非流式输出)
function addItem(title: string, content: string) {
  const obj = {
    title: title,
    content: content,
  };
  data.value.push(obj);

  nextTick(() => {
    chatContainer.value.$el.scrollTop = chatContainer.value.$el.scrollHeight;
  });
}

// 流式输出
function addItem2(value: string) {
  currItem.value = data.value.pop();
  addAsPrint(value);
  data.value.push(currItem.value);

  nextTick(() => {
    chatContainer.value.$el.scrollTop = chatContainer.value.$el.scrollHeight;
  });
}

function addAsPrint(value) {
  if (!value) {
    return;
  }
  currItem.value.content += value
}

// 保存历史记录
function saveItemHis(title: string, content: string) {
  const item: QuestionHisForm = Object.assign(props.params, {
    remark: title,
    content: content,
  });
  saveQuestionHis(item).finally(() => {
    emits("done");
  });
}

// 调用接口回答问题
function getChat() {
  loading.value = true;
  addItem(props.obj.messageTitle, "");
  // 这里根据是否有知识库编号，不同调用不同接口
  if (props.knowledgeId) {
    // 与知识库对话
    queryParams.knowledge_base_id = props.knowledgeId;
    chatKnowledge(queryParams)
      .then((res) => {
        const value = res.response;
        data.value.pop();
        addItem(props.obj.messageTitle, value);
        saveItemHis(props.obj.messageTitle, value);
      })
      .finally(() => {
        loading.value = false;
      });
  } else {
    controller.isDone = false;
    controller.stop = false;
    chatApi(queryParams, (subContent) => {
      if (subContent.includes("[DONE]")) {
        emits("done");
        loading.value = false;
        controller.isDone = true;
        controller.stop = true;
        saveItemHis(props.obj.messageTitle, currItem.value.content);
      } else {
        addItem2(subContent);
      }
    });
  }
}

// 复制标题到对话框
function onClickTitle(title: string) {
  if (loading.value) {
    return;
  }
  emits("reChat", "");
  nextTick(() => {
    emits("reChat", title);
  });
}

onMounted(() => {
  if (props.obj.messageTitle.slice(props.obj.messageTitle.length - 1) === "&") {
    let newTitle = props.obj.messageTitle.slice(0, -1);
    getQuestionHisForm(props.obj.messageId).then((res) => {
      addItem(newTitle, res.data.content);
    });
  } else {
    queryParams.question = props.obj.messageTitle;
    getChat();
  }
});
</script>

<style lang="scss" scoped>
.chat-body {
  height: 100%;
  width: 100%;
  padding: 0 0 20px;
  overflow-y: auto;
  border: none;
  font-size: var(--el-font-size-base);

  .message-top {
    display: flex;
    align-items: center;
    margin-bottom: 19px;

    img {
      width: 30px;
      height: 30px;
      margin-right: 16px;
    }

    .message-text {
      font-weight: 400;
      color: var(--el-text-color-primary);
      cursor: pointer;
    }
  }

  .message-card {
    padding: 17px 5px;
    border: 1px solid var(--el-dialog-bg-color);
    border-radius: 8px;
    overflow-y: auto;
    margin-bottom: 26px;

    .message-top-title {
      display: flex;
      align-items: flex-start;
      margin-bottom: 20px;

      .markdown-viewer {
        margin-top: 10px;
      }

      img {
        width: 30px;
        height: 30px;
        margin-right: 5px;
      }

      .message-title {
        font-weight: 400;
        color: var(--el-text-color-primary);
      }

      :deep(.markdown-viewer) {
        margin-top: -5px;
      }
    }
  }

  .message-stop {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 143px;
    height: 57px;
    border-radius: 7px;
    background: var(--el-fill-color);
    cursor: pointer;

    .message-text {
      margin-left: 2px;
      font-weight: 400;
      font-size: 14px;
      color: var(--el-text-color-primary);
    }
  }

  :deep(.md-editor-preview-wrapper) {
    padding: 0px 20px;

    .md-editor-preview {
      font-size: calc(var(--el-font-size-base) + 2px);
    }
  }

  .message-loading {
    margin-top: 14px;
  }
}
</style>
